package com.fxkj.cloud.drms.infra.repository;

import com.fasterxml.jackson.core.type.TypeReference;
import com.fxkj.cloud.drms.domain.alarm.AlarmHistoryDomain;
import com.fxkj.cloud.drms.domain.alarm.AlarmStatistics;
import com.fxkj.cloud.drms.domain.alarm.repository.AlarmHistoryDomainRepository;
import com.fxkj.cloud.drms.infra.converter.AlarmHistoryConverter;
import com.fxkj.cloud.drms.infra.persistence.dao.AlarmHistoryJpaRepository;
import com.fxkj.cloud.drms.infra.persistence.po.AlarmHistoryPO;
import com.fxkj.cloud.drms.infra.persistence.po.AlarmStatisticsInfo;
import com.fxkj.common.utils.JacksonUtil;
import jakarta.persistence.criteria.Predicate;
import org.springframework.data.domain.*;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.UUID;

/**
 * <p>description: </p>
 * @author ww
 * @date 2025/4/7 15:30
 */
@Component
public class AlarmHistoryDomainRepositoryImpl implements AlarmHistoryDomainRepository {
    private final AlarmHistoryJpaRepository alarmHistoryJpaRepository;
    private final AlarmHistoryConverter alarmHistoryConverter;

    public AlarmHistoryDomainRepositoryImpl(AlarmHistoryJpaRepository alarmHistoryJpaRepository, AlarmHistoryConverter alarmHistoryConverter) {
        this.alarmHistoryJpaRepository = alarmHistoryJpaRepository;
        this.alarmHistoryConverter = alarmHistoryConverter;
    }

    @Override
    public Page<AlarmHistoryDomain> list(Pageable pageable, UUID deviceId, UUID productId, UUID orgId, Integer alarmLevel, Long startTs, Long endTs, String alarmText, Boolean closed) {

        Specification<AlarmHistoryPO> spec = (root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();  // 新增条件集合
            predicates.add(cb.equal(root.get("organizationId"), orgId));
            if (deviceId != null) {
                predicates.add(cb.equal(root.get("deviceId"), deviceId));
            }
            if (productId != null) {
                predicates.add(cb.equal(root.get("productId"), productId));
            }
            if (alarmLevel != null) {
                predicates.add(cb.equal(root.get("alarmLevel"), alarmLevel));
            }
            if (startTs != null) {
                predicates.add(cb.greaterThanOrEqualTo(root.get("startTs"), startTs));
            }
            if (endTs != null) {
                predicates.add(cb.lessThanOrEqualTo(root.get("startTs"), endTs));
            }
            if (alarmText != null) {
                predicates.add(cb.like(root.get("alarmText"), "%" + alarmText + "%"));
            }
            if (null != closed) {
                predicates.add(cb.equal(root.get("closed"), closed));
            }
            return cb.and(predicates.toArray(new Predicate[0]));
        };
        PageRequest pageRequest = PageRequest.of(pageable.getPageNumber(), pageable.getPageSize(), Sort.by(Sort.Direction.DESC, "startTs"));
        Page<AlarmHistoryPO> pageData = alarmHistoryJpaRepository.findAll(spec, pageRequest);

        return pageData.map(alarmHistoryConverter::toDomain);
    }

    @Override
    public void save(AlarmHistoryDomain alarmHistoryDomain) {
        alarmHistoryJpaRepository.save(alarmHistoryConverter.toPO(alarmHistoryDomain));
    }

    @Override
    public void saveAll(List<AlarmHistoryDomain> alarmHistoryDomains) {
        alarmHistoryJpaRepository.saveAll(alarmHistoryConverter.toPO(alarmHistoryDomains));
    }

    @Override
    public List<AlarmHistoryDomain> findByDeviceSerialNoAndCodeAndClose(String deviceSerialNo, String code, Boolean close) {
        return alarmHistoryConverter.toDomain(alarmHistoryJpaRepository.findByDeviceSerialNoAndAlarmCodeAndClosed(deviceSerialNo, code, close));
    }

    @Override
    public List<AlarmStatistics> productAlarmStatistics(Set<UUID> productIds) {
        return alarmHistoryConverter.toStatistics(JacksonUtil.convertValue(alarmHistoryJpaRepository.alarmStatisticsByProductIdIn(productIds), new TypeReference<List<AlarmStatisticsInfo>>() {
        }));
    }
}
